﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Model;
using System.Web.UI.DataVisualization.Charting;
using BusinessObject;
using System.Web.Services;

namespace ViewLayer.Pages.MonteCarlo
{
    public partial class Simulacao : System.Web.UI.Page
    {
        private User user;
        private Project projeto;
        private string tipo;
        private string tipoFase;

        protected void Page_Load(object sender, EventArgs e)
        {
            user = (User)Session["User"];
            projeto = (Project)Session["Project"];
            tipo = (string)Session["Tipo"];
            tipoFase = (string)Session["TipoFase"];

            if (user == null)
            {
                Response.Redirect("../../Account/Login.aspx");
            }
            if (projeto != null)
            {
                this.lblNomeProjeto.Text = projeto.Nome;
            }
        }

        [WebMethod]
        public static List<DataChart> GetData(string id, string iterations)
        {
            IList<int> selectedIds = new List<int>();
            var tipoSimulacao = HttpContext.Current.Session["Tipo"];

            string[] selected = id.Split(',');

            for (int i = 0; i < selected.Length; i++)
            {
                selectedIds.Add(int.Parse(selected[i]));
            }

            IList<int> result = new List<int>();

            if (tipoSimulacao.Equals("Epic"))
            {
                IList<Epic> epics = EpicBO.Instance.getEpicByIds(selectedIds);
                var resultListEpic = MonteCarloSimulationBO<Epic>.Instance.monteCarloSimulation(int.Parse(iterations), epics);
                result = resultListEpic;
            }
            else if (tipoSimulacao.Equals("History"))
            {
                IList<History> historys = HistoryBO.Instance.getHistoryByIds(selectedIds);
                var resultListHistory = MonteCarloSimulationBO<History>.Instance.monteCarloSimulation(int.Parse(iterations), historys);
                result = resultListHistory;
            }
            else if (tipoSimulacao.Equals("Task"))
            {
                IList<Task> tasks = TaskBO.Instance.GetTaskByIds(selectedIds);
                var resultListTask = MonteCarloSimulationBO<Task>.Instance.monteCarloSimulation(int.Parse(iterations), tasks);
                result = resultListTask;
            }

            return getDataChart(result);
        }

        private static List<DataChart> getDataChart(IList<int> resultList)
        {
            List<DataChart> dataList = new List<DataChart>();

            if (resultList.Equals(null))
            {
                return null;
            }

            else
            {
                var final = resultList.Distinct().OrderBy(b => double.Parse(b.ToString()));
                double valorAcumulado = 0.0;
                string resultado = string.Empty;

                foreach (var a in final)
                {
                    //5frequency.Add(a.ToString(), resultList.Count(c => c == a));
                    valorAcumulado += resultList.Count(c => c == a);
                    //Response.Write(a.ToString() + "  ; " + (valorAcumulado / (double)resultList.Count + "<br />"));
                    resultado += a.ToString() + " ; " + (valorAcumulado / (double)resultList.Count + "<br />");

                    dataList.Add(new DataChart(a, valorAcumulado / (double)resultList.Count));
                }

                return dataList;
            }
        }

        protected void btnSimulate_Click(object sender, EventArgs e)
        {
            try
            {
                IList<int> selectedIds = new List<int>();

                foreach (GridViewRow row in grdResultado.Rows)
                {
                    if (isChecked(row))
                    {
                        int id = int.Parse(((HiddenField)row.FindControl("lblID")).Value);
                        selectedIds.Add(id);
                    }
                }

                IList<int> result = new List<int>();

                if (isFilled(txtIterations))
                {
                    lblMsgErrorFilling.Visible = false;
                    if (tipo.Equals("Epic"))
                    {
                        result = MonteCarloSimulationBO<Epic>.Instance.monteCarloSimulation(int.Parse(txtIterations.Text),
                            EpicBO.Instance.getEpicByIds(selectedIds));
                    }
                    else if (tipo.Equals("History"))
                    {
                        result = MonteCarloSimulationBO<History>.Instance.monteCarloSimulation(int.Parse(txtIterations.Text),
                            HistoryBO.Instance.getHistoryByIds(selectedIds));
                    }
                    else if (tipo.Equals("Task"))
                    {
                        result = MonteCarloSimulationBO<Task>.Instance.monteCarloSimulation(int.Parse(txtIterations.Text),
                            TaskBO.Instance.GetTaskByIds(selectedIds));
                    }
                    //plotGraphic(result);
                }
                else
                {
                    lblMsgErrorFilling.Visible = true;
                }
            }
            catch (Exception)
            {

            }
        }

        private bool isChecked(GridViewRow row)
        {
            return ((CheckBox)row.FindControl("ckbSelect")).Checked;
        }

        private bool isFilled(TextBox txt)
        {
            if (txt.Text.Equals("") || txt.Equals(null))
            {
                return false;
            }
            return true;
        }

        protected void btnSelect_Click(object sender, EventArgs e)
        {
            cleanUpGridViews();

            switch (ddlType.SelectedValue)
            {
                case "0":
                    lblMsgError.Visible = true;
                    break;
                case "1":
                    lblMsgError.Visible = false;
                    populateGrdResultadoWithEpic();
                    break;
                case "2":
                    lblMsgError.Visible = false;
                    populateGrdResultadoWithHistory();
                    break;
                case "3":
                    lblMsgError.Visible = false;
                    populateGrdResultadoWithTask();
                    break;
                case "4":
                    lblMsgError.Visible = false;
                    if (string.IsNullOrEmpty(txtDataFase.Text) || string.IsNullOrWhiteSpace(txtDataFase.Text))
                    {
                        grdFase.DataSource = ReleaseBO.Instance.GetReleaseByProject(projeto);
                    }
                    else
                    {
                        grdFase.DataSource = ReleaseBO.Instance.GetReleaseByProjectByDate(projeto, DateTime.Parse(txtDataFase.Text));
                    }
                    Session["TipoFase"] = "Release";
                    grdFase.Visible = true;
                    grdFase.DataBind();
                    break;
                case "5":
                    lblMsgError.Visible = false;
                    if (string.IsNullOrEmpty(txtDataFase.Text) || string.IsNullOrWhiteSpace(txtDataFase.Text))
                    {
                        grdFase.DataSource = SprintBO.Instance.GetSprintByProject(projeto);
                    }
                    else
                    {
                        grdFase.DataSource = SprintBO.Instance.GetSprintByProjectByDate(projeto, DateTime.Parse(txtDataFase.Text));
                    }
                    Session["TipoFase"] = "Sprint";
                    grdFase.Visible = true;
                    grdFase.DataBind();
                    break;
                default:
                    break;
            }
        }

        private void cleanUpGridViews()
        {
            grdFase.DataSource = null;
            grdFase.DataBind();
            grdResultado.DataSource = null;
            grdResultado.DataBind();
        }

        private void populateGrdResultadoWithTask()
        {
            grdResultado.DataSource = TaskBO.Instance.GetTaskByProject(projeto);
            Session["Tipo"] = "Task";
            grdResultado.DataBind();
        }

        private void populateGrdResultadoWithHistory()
        {
            grdResultado.DataSource = HistoryBO.Instance.GetHistoryByProject(projeto);
            Session["Tipo"] = "History";
            grdResultado.DataBind();
        }

        private void populateGrdResultadoWithEpic()
        {
            grdResultado.DataSource = EpicBO.Instance.GetEpicByProject(projeto);
            Session["Tipo"] = "Epic";
            grdResultado.DataBind();
        }

        protected void grdResultado_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                if (Session["Tipo"].Equals("Epic"))
                {
                    Epic epic = e.Row.DataItem as Epic;
                    populateRows(e, epic);

                }
                else if (Session["Tipo"].Equals("History"))
                {
                    History historia = e.Row.DataItem as History;
                    populateRows(e, historia);
                }
                else if (Session["Tipo"].Equals("Task"))
                {
                    Task tarefa = e.Row.DataItem as Task;
                    populateRows(e, tarefa);
                }
            }
        }

        protected void grdFase_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            populateDdlPhaseType();

            if (Session["TipoFase"].Equals("Release"))
            {
                if (e.Row.RowType == DataControlRowType.DataRow)
                {
                    Release release = e.Row.DataItem as Release;
                    (e.Row.FindControl("lblNomeFase") as Label).Text = release.Nome;
                    if (release.DataInicio.HasValue)
                    {
                        (e.Row.FindControl("lblDataInicioFase") as Label).Text = release.DataInicio.Value.ToString("dd/MM/yyyy");
                    }
                    if (release.DataFim.HasValue)
                    {
                        (e.Row.FindControl("lblDataTerminoFase") as Label).Text = release.DataFim.Value.ToString("dd/MM/yyyy");
                    }
                    (e.Row.FindControl("btnVisualizar") as Button).CommandArgument = release.Id.ToString();
                }
            }
            else if (Session["TipoFase"].Equals("Sprint"))
            {
                if (e.Row.RowType == DataControlRowType.DataRow)
                {
                    Sprint sprint = e.Row.DataItem as Sprint;
                    (e.Row.FindControl("lblNomeFase") as Label).Text = sprint.Nome;
                    (e.Row.FindControl("lblDataInicioFase") as Label).Text = sprint.DataInicio.ToString("dd/MM/yyyy");
                    (e.Row.FindControl("lblDataTerminoFase") as Label).Text = sprint.DataFim.ToString("dd/MM/yyyy");
                    (e.Row.FindControl("btnVisualizar") as Button).CommandArgument = sprint.Id.ToString();
                }
            }
        }

        private void populateDdlPhaseType()
        {
            ddlPhaseType.Visible = true;
            ddlPhaseType.Items.Clear();
            ddlPhaseType.Items.Add(new ListItem("Selecione...", "0"));

            if (Session["TipoFase"].Equals("Release"))
            {
                ddlPhaseType.Items.Add(new ListItem("Epic", "1"));
                ddlPhaseType.Items.Add(new ListItem("Historia", "2"));
            }
            else if (Session["TipoFase"].Equals("Sprint"))
            {
                ddlPhaseType.Items.Add(new ListItem("Historia", "1"));
                ddlPhaseType.Items.Add(new ListItem("Tarefa", "2"));
            }
        }


        protected void grdFase_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            if (ddlPhaseType.SelectedValue == "1" || ddlPhaseType.SelectedValue == "2")
            {
                lblMsgErroTipoFase.Visible = false;
                if (e.CommandName.Equals("Visualizar"))
                {
                    if (Session["TipoFase"].Equals("Release"))
                    {
                        if (ddlPhaseType.SelectedValue == "1")
                        {
                            grdResultado.DataSource = EpicBO.Instance.GetEpicByRelease(ReleaseBO.Instance.GetById(Convert.ToInt32(e.CommandArgument)));
                            Session["Tipo"] = "Epic";
                            grdResultado.DataBind();
                        }
                        else if (ddlPhaseType.SelectedValue == "2")
                        {
                            IList<History> historiasRelease = new List<History>();

                            foreach (Epic epic in EpicBO.Instance.GetEpicByRelease(ReleaseBO.Instance.GetById(Convert.ToInt32(e.CommandArgument))))
                            {
                                IList<History> historiasEpic = new List<History>();
                                historiasEpic = HistoryBO.Instance.GetHistoryByEpic(epic);
                                foreach (History history in historiasEpic)
                                {
                                    historiasRelease.Add(history);
                                }
                            }
                            foreach (History historiaSemEpic in HistoryBO.Instance.GetHistoryWithoutEpic())
                            {
                                historiasRelease.Add(historiaSemEpic);
                            }

                            grdResultado.DataSource = historiasRelease;
                            Session["Tipo"] = "History";
                            grdResultado.DataBind();
                        }
                    }
                    else if (Session["TipoFase"].Equals("Sprint"))
                    {
                        if (ddlPhaseType.SelectedValue == "1")
                        {
                            grdResultado.DataSource = HistoryBO.Instance.GetHistoryByOrWithoutSprint(SprintBO.Instance.GetById(Convert.ToInt32(e.CommandArgument)));
                            Session["Tipo"] = "History";
                            grdResultado.DataBind();
                        }
                        else if (ddlPhaseType.SelectedValue == "2")
                        {
                            grdResultado.DataSource = TaskBO.Instance.GetTaskByOrWithoutSprint(SprintBO.Instance.GetById(Convert.ToInt32(e.CommandArgument)));
                            Session["Tipo"] = "Task";
                            grdResultado.DataBind();
                        }
                    }
                }
            }
            else
            {
                lblMsgErroTipoFase.Visible = true;
            }
        }

        private void populateRows(GridViewRowEventArgs e, object item)
        {

            if (item is Epic)
            {
                populateEpicRows(e, (Epic)item);
            }
            else if (item is History)
            {
                populateHistoryRows(e, (History)item);
            }
            else if (item is Task)
            {
                populateTaskRows(e, (Task)item);
            }
        }

        private void populateEpicRows(GridViewRowEventArgs e, Epic item)
        {
            //exibição
            (e.Row.FindControl("lblID") as HiddenField).Value = item.Id.ToString();
            (e.Row.FindControl("lblNome") as Label).Text = item.Nome;
            (e.Row.FindControl("lblMelhorCaso") as Label).Text = item.MelhorCaso.ToString();
            (e.Row.FindControl("lblMaisProvavel") as Label).Text = item.CasoMedio.ToString();
            (e.Row.FindControl("lblPiorCaso") as Label).Text = item.PiorCaso.ToString();
            //(e.Row.FindControl("lblAssociado") as Label).Text = item.Release.Nome;

            //edição
            (e.Row.FindControl("txtNome") as TextBox).Text = item.Nome;
            (e.Row.FindControl("txtMelhorCaso") as TextBox).Text = item.MelhorCaso.ToString();
            (e.Row.FindControl("txtMaisProvavel") as TextBox).Text = item.CasoMedio.ToString();
            (e.Row.FindControl("txtPiorCaso") as TextBox).Text = item.PiorCaso.ToString();
            (e.Row.FindControl("btnSalvar") as Button).CommandArgument = item.Id.ToString();

            DropDownList ddlToAssociate = e.Row.FindControl("ddlToAssociate") as DropDownList;

            populateToAssociate(ddlToAssociate);
            if (item.Release != null)
            {
                ddlToAssociate.SelectedIndex = item.Release.Id;
                (e.Row.FindControl("lblAssociado") as Label).Text = item.Release.Nome;
            }
        }

        private void populateToAssociate(DropDownList ddlToAssociate)
        {
            var sessionType = Session["Tipo"].ToString();

            if (sessionType == "Epic")
            {
                ddlToAssociate.DataSource = ReleaseBO.Instance.GetReleaseByProject(Session["Project"] as Project);
                ddlToAssociate.DataTextField = "Nome";
                ddlToAssociate.DataValueField = "Id";
                ddlToAssociate.DataBind();

                ddlToAssociate.Items.Add(new ListItem("Sem Associação", "0"));
                ddlToAssociate.SelectedValue = "0";
            }
            else if (sessionType == "History")
            {
                ddlToAssociate.DataSource = SprintBO.Instance.GetSprintByProject(Session["Project"] as Project);
                ddlToAssociate.DataTextField = "Nome";
                ddlToAssociate.DataValueField = "Id";
                ddlToAssociate.DataBind();

                ddlToAssociate.Items.Add(new ListItem("Sem Associação", "0"));
                ddlToAssociate.SelectedValue = "0";
            }
            else if (sessionType == "Task")
            {
                ddlToAssociate.DataSource = SprintBO.Instance.GetSprintByProject(Session["Project"] as Project);
                ddlToAssociate.DataTextField = "Nome";
                ddlToAssociate.DataValueField = "Id";
                ddlToAssociate.DataBind();

                ddlToAssociate.Items.Add(new ListItem("Sem Associação", "0"));
                ddlToAssociate.SelectedValue = "0";
            }
        }

        private void populateHistoryRows(GridViewRowEventArgs e, History item)
        {
            //exibição
            (e.Row.FindControl("lblID") as HiddenField).Value = item.Id.ToString();
            (e.Row.FindControl("lblNome") as Label).Text = item.Nome;
            (e.Row.FindControl("lblMelhorCaso") as Label).Text = item.MelhorCaso.ToString();
            (e.Row.FindControl("lblMaisProvavel") as Label).Text = item.CasoMedio.ToString();
            (e.Row.FindControl("lblPiorCaso") as Label).Text = item.PiorCaso.ToString();
            //(e.Row.FindControl("lblAssociado") as Label).Text = item.Sprint.Nome;

            //edição
            (e.Row.FindControl("txtNome") as TextBox).Text = item.Nome;
            (e.Row.FindControl("txtMelhorCaso") as TextBox).Text = item.MelhorCaso.ToString();
            (e.Row.FindControl("txtMaisProvavel") as TextBox).Text = item.CasoMedio.ToString();
            (e.Row.FindControl("txtPiorCaso") as TextBox).Text = item.PiorCaso.ToString();
            (e.Row.FindControl("btnSalvar") as Button).CommandArgument = item.Id.ToString();

            DropDownList ddlToAssociate = e.Row.FindControl("ddlToAssociate") as DropDownList;

            populateToAssociate(ddlToAssociate);
            if (item.Sprint != null)
            {
                ddlToAssociate.SelectedIndex = item.Sprint.Id;
                (e.Row.FindControl("lblAssociado") as Label).Text = item.Sprint.Nome;
            }
        }

        private void populateTaskRows(GridViewRowEventArgs e, Task item)
        {
            //exibição
            (e.Row.FindControl("lblID") as HiddenField).Value = item.Id.ToString();
            (e.Row.FindControl("lblNome") as Label).Text = item.Nome;
            (e.Row.FindControl("lblMelhorCaso") as Label).Text = item.MelhorCaso.ToString();
            (e.Row.FindControl("lblMaisProvavel") as Label).Text = item.CasoMedio.ToString();
            (e.Row.FindControl("lblPiorCaso") as Label).Text = item.PiorCaso.ToString();
            //(e.Row.FindControl("lblAssociado") as Label).Text = item.Sprint.Nome;

            //edição
            (e.Row.FindControl("txtNome") as TextBox).Text = item.Nome;
            (e.Row.FindControl("txtMelhorCaso") as TextBox).Text = item.MelhorCaso.ToString();
            (e.Row.FindControl("txtMaisProvavel") as TextBox).Text = item.CasoMedio.ToString();
            (e.Row.FindControl("txtPiorCaso") as TextBox).Text = item.PiorCaso.ToString();
            (e.Row.FindControl("btnSalvar") as Button).CommandArgument = item.Id.ToString();

            DropDownList ddlToAssociate = e.Row.FindControl("ddlToAssociate") as DropDownList;

            populateToAssociate(ddlToAssociate);
            if (item.Sprint != null)
            {
                ddlToAssociate.SelectedIndex = item.Sprint.Id;
                (e.Row.FindControl("lblAssociado") as Label).Text = item.Sprint.Nome;
            }
        }

        /// <summary>
        /// Gerencia os controles dos campos na página.
        /// </summary>
        /// <param name="grd"></param>
        /// <param name="editar"></param>
        private static void ControlsVisibilityManager(GridViewRow grd, bool editar)
        {
            (grd.FindControl("txtNome") as TextBox).Visible = editar;
            (grd.FindControl("txtMelhorCaso") as TextBox).Visible = editar;
            (grd.FindControl("txtMaisProvavel") as TextBox).Visible = editar;
            (grd.FindControl("txtPiorCaso") as TextBox).Visible = editar;
            (grd.FindControl("ddlToAssociate") as DropDownList).Visible = editar;
            (grd.FindControl("btnSalvar") as Button).Visible = editar;

            (grd.FindControl("lblNome") as Label).Visible = !editar;
            (grd.FindControl("lblMelhorCaso") as Label).Visible = !editar;
            (grd.FindControl("lblMaisProvavel") as Label).Visible = !editar;
            (grd.FindControl("lblPiorCaso") as Label).Visible = !editar;
            (grd.FindControl("lblAssociado") as Label).Visible = !editar;
            (grd.FindControl("btnAtualizar") as Button).Visible = !editar;
        }

        protected void grdResultado_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            GridViewRow grd = (GridViewRow)((Control)e.CommandSource).NamingContainer;

            if (e.CommandName.ToLower() == "editar")
            {
                ControlsVisibilityManager(grd, true);
            }

            if (e.CommandName.ToLower() == "salvar")
            {
                if (tipo == "Epic")
                {
                    UpdateEpic(e, grd);
                }
                else if (tipo == "History")
                {
                    UpdateHistory(e, grd);
                }
                else if (tipo == "Task")
                {
                    UpdateTask(e, grd);
                }
                else
                { }

                ControlsVisibilityManager(grd, false);
            }
        }

        private void UpdateEpic(GridViewCommandEventArgs e, GridViewRow grd)
        {
            Epic epic = EpicBO.Instance.GetById(Convert.ToInt32(e.CommandArgument));

            epic.Nome = (grd.FindControl("txtNome") as TextBox).Text;
            epic.MelhorCaso = Convert.ToDouble((grd.FindControl("txtMelhorCaso") as TextBox).Text);
            epic.CasoMedio = Convert.ToDouble((grd.FindControl("txtMaisProvavel") as TextBox).Text);
            epic.PiorCaso = Convert.ToDouble((grd.FindControl("txtPiorCaso") as TextBox).Text);

            var releaseIndex = Convert.ToInt32((grd.FindControl("ddlToAssociate") as DropDownList).SelectedValue);

            //sprint to associate
            if (releaseIndex > 0)
            {
                epic.Release = ReleaseBO.Instance.GetById(releaseIndex);
            }
            else
            {
                epic.Release = null;
            }

            EpicBO.Instance.Update(epic);

            populateGrdResultadoWithEpic();
        }

        private void UpdateHistory(GridViewCommandEventArgs e, GridViewRow grd)
        {
            History history = HistoryBO.Instance.GetById(Convert.ToInt32(e.CommandArgument));

            history.Nome = (grd.FindControl("txtNome") as TextBox).Text;
            history.MelhorCaso = Convert.ToDouble((grd.FindControl("txtMelhorCaso") as TextBox).Text);
            history.CasoMedio = Convert.ToDouble((grd.FindControl("txtMaisProvavel") as TextBox).Text);
            history.PiorCaso = Convert.ToDouble((grd.FindControl("txtPiorCaso") as TextBox).Text);

            var sprIndex = Convert.ToInt32((grd.FindControl("ddlToAssociate") as DropDownList).SelectedValue);

            //sprint to associate
            if (sprIndex > 0)
            {
                history.Sprint = SprintBO.Instance.GetById(sprIndex);
            }
            else
            {
                history.Sprint = null;
            }

            HistoryBO.Instance.Update(history);

            populateGrdResultadoWithHistory();
        }

        private void UpdateTask(GridViewCommandEventArgs e, GridViewRow grd)
        {
            Task task = TaskBO.Instance.GetById(Convert.ToInt32(e.CommandArgument));

            task.Nome = (grd.FindControl("txtNome") as TextBox).Text;
            task.MelhorCaso = Convert.ToDouble((grd.FindControl("txtMelhorCaso") as TextBox).Text);
            task.CasoMedio = Convert.ToDouble((grd.FindControl("txtMaisProvavel") as TextBox).Text);
            task.PiorCaso = Convert.ToDouble((grd.FindControl("txtPiorCaso") as TextBox).Text);


            var sprIndex = Convert.ToInt32((grd.FindControl("ddlToAssociate") as DropDownList).SelectedValue);

            //sprint to associate
            if (sprIndex > 0)
            {
                task.Sprint = SprintBO.Instance.GetById(sprIndex);
            }
            else
            {
                task.Sprint = null;
            }

            TaskBO.Instance.Update(task);

            populateGrdResultadoWithTask();
        }

        protected void ddlType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ddlType.SelectedItem.Text.Equals("Release") || ddlType.SelectedItem.Text.Equals("Sprint"))
            {
                pnlDataFase.Visible = true;
            }
            else
            {
                pnlDataFase.Visible = false;
            }
        }
    }
}